#include "svcp.hpp"

static int get_cp_status(const char * path , int flag);
static void get_name(const char * path, char *fileName);
static void fn_Cp_File_to_File(int fd1 , int fd2);
static void fn_Cp_File_to_Dir(const char * file_path ,const char * dir_path);
static void fn_Cp_Dir_to_Dir(const char * dir_path1 ,const char * dir_path2);

static void get_name(const char * path, char *fileName)
{
    char tmp_path[1024] = {0};
    char * tmp_p = (char *)malloc(1024);
    char * p = NULL;
    
    //字符串处理
    strcpy(tmp_path , path);
    p = strtok(tmp_path , "/");
    strcpy(tmp_p , p);
    while(1)
    {
        p = strtok(NULL , "/");
        if(p == NULL)
        {
            break;
        }
        else
        {
            strcpy(tmp_p , p);
        }
    }
    
	memcpy(fileName, tmp_p, strlen(tmp_p) + 1);
	free(tmp_p);
    tmp_p = NULL;

    return;
}

//返回值：0（路径为目录） ， 返回值大于0（路径为文件） ， 返回-1：打开文件失败
static int get_cp_status(const char * path , int flag)
{
    int fd = -1;

    if(flag == 7)
    {
        fd = open(path , O_RDWR | O_CREAT | O_TRUNC, 0600);
    }
    else
    {
        fd = open(path , O_RDWR);
    }
    
    if(fd <= 0)
    {
        if(errno == EISDIR)
        {
            return 0;
        }
        else
        {
            perror("错误原因");
            return -1;
        }
    }
    else
    {
        return fd;
    }
}

static void fn_Cp_File_to_File(int fd1 , int fd2)
{
    char tmp_buf[1024] = {0};
    while(1)
    {
        int ret = read(fd1 , tmp_buf , 1024);
        if(ret <= 0)
        {
            break;
        }
        ret = write(fd2 , tmp_buf , ret);
    }
}

static void fn_Cp_File_to_Dir(const char * file_path ,const char * dir_path)
{
	int ret = -1;
	char *cur_path = NULL;
    char cp_path[1024] = {0};
	char dest_path[1024] = {0};
    int file1_fd = 0;
    int file2_fd = 0;
	
	char fileName[1024] = {0};
	
    file1_fd = open(file_path , O_RDWR);

    //获得目标文件夹路径
	// printf("dir_path = %s\n", dir_path);
    ret = chdir(dir_path);
    cur_path = getcwd(cp_path , 1024);
	get_name(file_path, fileName);
	
    snprintf(dest_path, sizeof(dest_path), "%s/%s", cur_path, fileName);
	
    file2_fd = open(dest_path , O_RDWR | O_CREAT | O_TRUNC, 0600);
    fn_Cp_File_to_File(file1_fd , file2_fd);

    close(file1_fd);
    close(file2_fd);
}

static void fn_Cp_Dir_to_Dir(const char * dir_path1 ,const char * dir_path2)
{
    DIR * dp = NULL;
	char *cur_path = NULL;
	int chdir_ret = -1;
	
    struct dirent * dir_info;
    char cp_path_begin[1024] = {0};
    char cp_path_from[1024] = {0};
    char cp_path_to[1024] = {0};
	char fileName[1024] = {0};

    cur_path = getcwd(cp_path_begin , 1024);

    //获得完整的路径1
    if(dir_path1[0] == '~' || dir_path1[0] == '/')
    {
        strcpy(cp_path_from , dir_path1);
        printf("cp_path from:%s\n" , cp_path_from);
    }
    else
    {
        chdir_ret = chdir(dir_path1);
        cur_path = getcwd(cp_path_from , 1024);
        chdir_ret = chdir(cp_path_begin);
        printf("cp_path from:%s\n" , cp_path_from);
    }

    //获得完整的路径2
    if(dir_path2[0] == '~' || dir_path2[0] == '/')
    {
        strcpy(cp_path_to , dir_path2);
        printf("cp_path to:%s\n" , cp_path_to);
        mkdir(cp_path_to , 0777);
    }
    else
    {
        chdir_ret = chdir(dir_path2);
        cur_path = getcwd(cp_path_to , 1024);
        chdir_ret = chdir(cp_path_begin);
        //创建被复制的目录
		get_name(dir_path1, fileName);
        sprintf(cp_path_to , "%s/%s" , cp_path_to , fileName);
        printf("cp_path to:%s\n" , cp_path_to);
        mkdir(cp_path_to , 0777);
    }

    //开始复制
    dp = opendir(cp_path_from);
    while(1)
    {
        dir_info = readdir(dp);
        if(dir_info == NULL)
        {
            break;
        }
        if(dir_info->d_type == DT_DIR)
        {
            //排除.和..
            if((strcmp(dir_info->d_name , ".") == 0) || (strcmp(dir_info->d_name , "..") == 0))
            { 
                continue;
            }
            //重新拼接目录
            char cp_path_from_r[1024] = {0};
            char cp_path_to_r[1024] = {0};
            sprintf(cp_path_from_r , "%s/%s" , cp_path_from , dir_info->d_name);
            sprintf(cp_path_to_r , "%s/%s" , cp_path_to , dir_info->d_name);
            fn_Cp_Dir_to_Dir(cp_path_from_r , cp_path_to_r);
        }
        else
        {
            char file_path[1024] = {0};
            sprintf(file_path , "%s/%s" , cp_path_from , dir_info->d_name);
            fn_Cp_File_to_Dir(file_path , cp_path_to);
        }
    }
    closedir(dp);
    return;
}

int32_t svcp(char *src_path, char *dest_path)
{
    int Path1_fd;
    int Path2_fd;

    //判断传参路径是什么文件，普通文件则打开，目录文件返回0，返回值是文件描述符
    Path1_fd = get_cp_status(src_path, FILE_RDWR);
    Path2_fd = get_cp_status(dest_path, FILE_RDWR + FILE_CREATE + FILE_TUNC);

    //打开文件出错
    if(Path1_fd < 0 || Path2_fd < 0)
    {
        return 0;
    }

    //文件间复制
    if(Path1_fd > 0 && Path2_fd > 0)
    {
        fn_Cp_File_to_File(Path1_fd , Path2_fd);
        close(Path1_fd);
        close(Path2_fd);
    }
    
    //文件到目录复制
    if(Path1_fd > 0 && Path2_fd == 0)
    {
        close(Path1_fd);
        fn_Cp_File_to_Dir(src_path , dest_path);
    }
    
    //目录到目录复制
    if(Path1_fd == 0 && Path2_fd == 0)
    {
        fn_Cp_Dir_to_Dir(src_path, dest_path);
    }

    return 0;
}
